#include "stdafx.h"

#include "hwinfiledialog.h"
#include "hwincontrol.h"


namespace harlinn
{
    namespace windows
    {
        // ----------------------------------------------------------------------
        // ModalWindow
        // ----------------------------------------------------------------------
        HWIN_EXPORT bool ModalWindow::Show(HWND theOwner)
        {
            auto pInterface = GetInterface();
            auto hr = pInterface->Show(theOwner);
            if(hr == S_OK)
            {
                return true;
            }
            else if(hr != HRESULT_FROM_WIN32(ERROR_CANCELLED))
            {
                if(FAILED(hr))
                {
                    CheckHRESULT(hr);
                }
            }
            return false;
        }


        HWIN_EXPORT bool ModalWindow::Show( const std::shared_ptr<Control>& theOwner )
        {
            return this->Show(theOwner->GetSafeHandle());
        }

        // ----------------------------------------------------------------------
        // FileDialogEvents
        // ----------------------------------------------------------------------
        
        HWIN_EXPORT FileDialogEventsImplementation::FileDialogEventsImplementation(FileDialog* theFileDialog)
            : fileDialog(theFileDialog)
        {
        }

        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnFileOk(IFileDialog *pfd)
        {
            if(fileDialog)
            {
                bool accept = true;
                fileDialog->DoOnFileOk(accept);
                return accept?S_OK:S_FALSE;
            }
            return S_OK;
        }
        
        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnFolderChanging(IFileDialog *pfd,IShellItem *psiFolder)
        {
            if(fileDialog)
            {
                IShellItem2* pShellItem2 = nullptr;
                auto hr = psiFolder->QueryInterface(&pShellItem2);
                if(FAILED(hr))
                {
                    return hr;
                }
                ShellItem shellItem(pShellItem2);
                bool accept = true;
                fileDialog->DoOnFolderChanging(shellItem,accept);
                return accept?S_OK:S_FALSE;
            }
            return S_OK;
        }
        
        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnFolderChange(IFileDialog *pfd)
        {
            if(fileDialog)
            {
                fileDialog->DoOnFolderChange();
            }
            return S_OK;
        }
        
        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnSelectionChange(IFileDialog *pfd)
        {
            if(fileDialog)
            {
                fileDialog->DoOnSelectionChange();
            }
            return S_OK;
        }
        
        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnShareViolation(IFileDialog *pfd,IShellItem *psi,FDE_SHAREVIOLATION_RESPONSE *pResponse)
        {
            if(fileDialog)
            {
                IShellItem2* pShellItem2 = nullptr;
                auto hr = psi->QueryInterface(&pShellItem2);
                if(FAILED(hr))
                {
                    return hr;
                }
                ShellItem shellItem(pShellItem2);
                
                FDE_SHAREVIOLATION_RESPONSE response = FDESVR_DEFAULT;

                fileDialog->DoOnShareViolation(shellItem,response);
                if(pResponse)
                {
                    *pResponse = response;
                }
            }
            return S_OK;
        }
        
        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnTypeChange(IFileDialog *pfd)
        {
            if(fileDialog)
            {
                fileDialog->DoOnTypeChange();
            }
            return S_OK;
        }
        
        HWIN_EXPORT HRESULT STDMETHODCALLTYPE FileDialogEventsImplementation::OnOverwrite(IFileDialog *pfd,IShellItem *psi,FDE_OVERWRITE_RESPONSE *pResponse)
        {
            if(fileDialog)
            {
                IShellItem2* pShellItem2 = nullptr;
                auto hr = psi->QueryInterface(&pShellItem2);
                if(FAILED(hr))
                {
                    return hr;
                }
                ShellItem shellItem(pShellItem2);
                
                FDE_OVERWRITE_RESPONSE response = FDEOR_DEFAULT;

                fileDialog->DoOnOverwrite(shellItem,response);
                if(pResponse)
                {
                    *pResponse = response;
                }
            }
            return S_OK;
        }

        // ----------------------------------------------------------------------
        // FileDialog
        // ----------------------------------------------------------------------

        HWIN_EXPORT bool FileDialog::Show(HWND theOwner)
        {
            bool result = false;
            FileDialogEvents fileDialogEvents( new FileDialogEventsImplementation(this) );
            DWORD cookie = Advise(fileDialogEvents);
            try
            {
                result = Base::Show(theOwner);
                Unadvise(cookie);
            }
            catch(...)
            {
                Unadvise(cookie);
                throw;
            }
            return result;
        }

        HWIN_EXPORT void FileDialog::DoOnFileOk( bool& accept )
        {
            OnFileOk( this, accept );
        }

        HWIN_EXPORT void FileDialog::DoOnFolderChanging(const ShellItem& newFolder, bool& allow)
        {
            OnFolderChanging(this,newFolder, allow);
        }
        
        HWIN_EXPORT void FileDialog::DoOnFolderChange()
        {
            OnFolderChange(this);
        }
        
        HWIN_EXPORT void FileDialog::DoOnSelectionChange( )
        {
            OnSelectionChange( this );
        }
        
        HWIN_EXPORT void FileDialog::DoOnShareViolation(const ShellItem& shellItem, FDE_SHAREVIOLATION_RESPONSE& response)
        {
            OnShareViolation(this,shellItem, response);
        }
        
        HWIN_EXPORT void FileDialog::DoOnTypeChange()
        {
            OnTypeChange(this);
        }
        
        HWIN_EXPORT void FileDialog::DoOnOverwrite(const ShellItem& shellItem, FDE_OVERWRITE_RESPONSE& response)
        {
            OnOverwrite(this, shellItem, response);
        }


        // ----------------------------------------------------------------------
        // FileOpenDialog
        // ----------------------------------------------------------------------
        HWIN_EXPORT std::shared_ptr<FileOpenDialog> FileOpenDialog::Create()
        {
            IFileOpenDialog* pDialog = nullptr;
            auto hr = CoCreateInstance(CLSID_FileOpenDialog,NULL,CLSCTX_INPROC_SERVER,__uuidof(IFileOpenDialog),(void**)&pDialog);
            if(FAILED(hr))
            {
                CheckHRESULT(hr);
            }

            auto result = std::make_shared<FileOpenDialog>(pDialog);
            return result;

        }

        // ----------------------------------------------------------------------
        // FileSaveDialog
        // ----------------------------------------------------------------------
        HWIN_EXPORT std::shared_ptr<FileSaveDialog> FileSaveDialog::Create()
        {
            IFileSaveDialog* pDialog = nullptr;
            auto hr = CoCreateInstance(CLSID_FileSaveDialog,NULL,CLSCTX_INPROC_SERVER,__uuidof(IFileSaveDialog),(void**)&pDialog);
            if(FAILED(hr))
            {
                CheckHRESULT(hr);
            }

            auto result = std::make_shared<FileSaveDialog>(pDialog);
            return result;

            
        }

    }
}